Skip to main content

Python openpyxl

Table of Contents

python excel 模块

安装

 $ pip install openpyxl
$ pip list | grep openpyxl
> openpyxl 3.0.10

创建读取

创建表

 from openpyxl import Workbook

wb = Workbook() # 创建一个工作表
sheet = wb.active # 激活第一个 sheet
sheet['A1'] = 'hellow world' # sheet A1 赋值
wb.save('test.xlsx') # 保存 excel 文件为 test.xlsx
wb.close() # 关闭工作表


wb.create_sheet(name:str [, index:int = -1]) # 自定义 sheet 名称和位置
wb.create_sheet('first_sheet', 0) # 在 0 插入 名为 first_sheet 的表
sheet.title # 获取sheet 的名称, 也可以重新赋值
> first_sheet

for sheet in wb: # 遍历工作表, 打印所有表名称
print(sheet.title)

wb.remove(sheet) # 删除 sheet, 参数是 sheet 对象

读取表

 from openpyxl import load_workbook

wb = load_workbook('test.xlsx') # 打开一个已存在的 excel 文件
sheet_names = wb.sheetnames # 获取所有表名组成的列表
> ['first', 'second', 'third']

sheet = wb['first']
sheet['A1']
> 'hellow world'

读写

赋值和读取

 sheet['A1'] = 'hellow world'                    # A1 赋值 hellow world
sheet['A1'].value # 读取 A1 方格的值
> 'hellow world'

sheet.cell(row=1, col=1).value = 'value' # 行 1, 列 1 赋值 value
grid = sheet.cell(row=1, column=1, value='ok') # 第一列第一行赋值 ok, 返回一个 cell 对象
sheel.cell(1, 1).value # 读取第一行第一列方格的值
> 'ok'

row_one = sheet['A1': 'F1'] # 获取多数方格, 返回 cell 对象的元组
sheet.max_column # 含有数据结束列
sheet.append([1, 2, 3, 4]) # 添加一行数据

多行遍历

  • sheet.iter_rows() 每次返回一整行组成的元组
  • sheet.iter_cols() 每次返回一整列组成的元组
参数含义
min_row起始行, default:None
max_row结束行, default:None
min_col起始列, default:None
max_col结束列, default:None
values_onlyTrue:只返回值, False: 返回 cell 对象

for row in sheet.iter_rows(
min_row=1, max_col=3, max_row=2): # 遍历第 1 至第 2 行, 取 3 列
for cell in row:
print(cell)

<Cell Sheet1.A1>
<Cell Sheet1.B1>
<Cell Sheet1.C1>
<Cell Sheet1.A2>
<Cell Sheet1.B2>
<Cell Sheet1.C2>

for col in sheet.iter_cols(
min_row=1, max_col=3, max_row=2): # 遍历第 1 至第 2 行, 取 3 列
for cell in col:
print(cell)

<Cell Sheet1.A1>
<Cell Sheet1.A2>
<Cell Sheet1.B1>
<Cell Sheet1.B2>
<Cell Sheet1.C1>
<Cell Sheet1.C2>

样式

字体

 from openpyxl.styles import Font

cell.font = Font(
name="微软雅黑", # 字体
size=15, # 字体大小
color="0000FF", # 字体颜色,用16进制rgb表示
bold=True, # 是否加粗,True/False
italic=True, # 是否斜体,True/False
strike=None, # 是否使用删除线,True/False
underline=None, # 下划线, 可选'singleAccounting', 'double', 'single', 'doubleAccounting'
)

填充颜色

 from openpyxl.styles import PatternFill

cell.fill = PatternFill(
patternType="solid", # 填充类型
fgColor="F562a4", # 前景色,16进制rgb
bgColor="0000ff", # 背景色,16进制rgb
)

patternType: # patternType 可选值
none、solid、darkGray、mediumGray、lightGray、
lightDown、lightGray、lightGrid

边框

 from openpyxl.styles import Border, Side

side = Side(
style="medium", # 边框样式
color="ff66dd", # 边框颜色,16进制rgb表示
)

style: # style 可选值
dashDot、dashDotDot、dashed、dotted、double、
hair、medium、mediumDashDot、mediumDashDotDot、
mediumDashed、slantDashDot、thick、thin

cell.border = Border(
top=side, # 上边框使用定义的 side
bottom=side, # 下边框使用定义的 side
left=side, # 左边框使用定义的 side
right=side, # 右边框使用定义的 side
diagonal=side # 对角线使用定义的 side
)

对齐

 from openpyxl.styles import Alignment

cell.alignment = Alignment(
horizontal='left', # 水平对齐,可选general、left、center、right、fill、justify、centerContinuous、distributed
vertical='top', # 垂直对齐, 可选top、center、bottom、justify、distributed
text_rotation=0, # 字体旋转,0~180整数
wrap_text=False, # 是否自动换行
shrink_to_fit=False, # 是否缩小字体填充
indent=0, # 缩进值
)

示例

class Excel:

def __init__(self, file, mode):
self.file = file
self.mode = mode
self.mode_init()

def __enter__(self):
return self

def __exit__(self, e_type, e_value, e_tb):
self.wb.close()
if any((e_type, e_value, e_tb)):
raise RuntimeError(f"error: {e_value}\n")

def mode_init(self):
""" 模式初始化
'w' 新建 excel 表格
'r' 读取 excel 表格
"""
if self.mode.lower() == 'w':
self.wb = Workbook()
self.sheet = self.wb.active
return

if self.mode.lower() == 'r':
self.wb = load_workbook(self.file, data_only=True)
self.sheet = self.wb[self.wb.sheetnames[0]]
self.head = self.read_head()
return

print(f'error mode {self.mode}, select r or w')
exit()

def cell_value(self, row, col):
""" 通过坐标读取值 """
return self.sheet.cell(row=row, column=col).value

def set_cell(self, row, col, value):
""" 通过坐标写入值 """
self.sheet.cell(row, col).value = value

def read_head(self):
""" 读取表格表头 """
max_col = self.sheet.max_column + 1
return [self.cell_value(1, col) for col in range(1, max_col)]

def select_column(self, select, key=None):
""" 选择属性对应的列
select 筛选需要输出的列

"""
if len(select) == 0:
select = self.head

if key != None and key not in select:
print(f"{key} not in {select}")
exit()

if set(self.head) < set(select):
print(f'{select} not in {self.head}')
exit()

return [self.head.index(k) for k in select if k in self.head]

def excel_to_list(self, select=[]):
""" 读取表格生成列表
select 筛选需要读取的列
"""
indexs = self.select_column(select)
excel_list = []

for row in range(2, self.sheet.max_row + 1):
excel_list.append({
self.head[col]: self.cell_value(row, col+1)
for col in indexs
})
return excel_list

def excel_to_dict(self, key, select=[]):
""" 读取表格生成字典, 一行一个字典
key 指定改行转成字典的 key
select 筛选需要输出的键值对
"""
indexs = self.select_column(select, key)
excel_dict = {}

for row in range(2, self.sheet.max_row + 1):
key_value = self.cell_value(row, self.head.index(key) + 1)
excel_dict.update({key_value: {
self.head[col]: self.cell_value(row, col+1)
for col in indexs
}})

return dict(sorted(excel_dict.items()))

def list_to_excel(self, lst, select=[]):
""" 列表生成表格
lst list[dict]: 字典列表
select 筛选需要输出的列
"""
try:
self.head = list(lst[0].keys())
except Exception as e:
print(f"data type error, must list[dict]")
exit()

indexs = self.select_column(select)
self.sheet.append([self.head[i] for i in indexs])
for line in lst:
self.sheet.append([line[self.head[i]] for i in indexs])

self.wb.save(self.file)

def dict_to_excel(self, dic, select=[]):
"""字典生成表格
dic dict[dict]: 双层字典
select 需要写入表格的键值对
"""
try:
self.head = list(list(dic.values())[0].keys())
except Exception as e:
print(f"data type error, must dict[str, dict]")
exit()

indexs = self.select_column(select)
self.sheet.append([self.head[i] for i in indexs])
for line in dic.values():
self.sheet.append([line[self.head[i]] for i in indexs])

self.wb.save(self.file)